using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using Microsoft.Win32;
using System.Security.Cryptography;
using System.Text;
using System.Linq;

namespace LicenseApp.Client
{
    /// <summary>
    /// 强化的使用天数计数器 - 防止删除数据攻击
    /// </summary>
    public class RobustUsageCounter
    {
        private const string REGISTRY_KEY = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
        private const string REGISTRY_VALUE = "TaskbarSizeMove_ZhyLsHK"; // 自定义后缀，确保唯一
        
        // 多个存储位置
        private readonly string[] _storagePaths;
        
        public RobustUsageCounter()
        {
            _storagePaths = new[]
            {
                // 用户主目录隐藏文件夹（主要存储位置）
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".CcdqLicenseApp", "usage.dat"),
                
                // 本地数据目录（协防位置1）
                //Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "LicenseApp", "usage.dat"),
                
                // 公共数据目录（协防位置2）
                //Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "LicenseApp", "usage.dat"),
                
                // 临时目录隐藏文件（协防位置3）
                //Path.Combine(Path.GetTempPath(), ".licenseapp_usage.dat"),
                
                //// 系统目录备份（协防位置4）
                //Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), ".licenseapp_backup.dat"),
                
                // 程序目录（协防位置5）
                "usage.dat"
            };
        }
        
        /// <summary>
        /// 验证使用天数（强化版）
        /// </summary>
        /// <param name="maxAllowedDays">最大允许天数</param>
        /// <param name="licenseStartDate">授权生效日期</param>
        public ValidationResult ValidateUsage(int maxAllowedDays, DateTime licenseStartDate)
        {
            try
            {
                Console.WriteLine("[RobustUsageCounter] 开始验证使用天数...");
                
                // 1. 从多个来源加载使用记录
                var records = LoadAllUsageRecords();
                
                // 2. 选择最可信的记录（使用天数最多的）
                var bestRecord = SelectBestRecord(records);
                var today = DateTime.Now.Date;
                
                Console.WriteLine($"[RobustUsageCounter] 找到 {records.Count} 个有效记录，最佳记录使用天数: {bestRecord?.UsedDays ?? 0}");
                
                // 3. 处理记录
                if (bestRecord == null)
                {
                    return HandleNoRecord(maxAllowedDays, licenseStartDate, today);
                }
                
                // 4. 更新使用天数
                if (today > bestRecord.LastUsedDate.Date)
                {
                    // 🐛 修复：计算基于授权生效日期的实际使用天数
                    var actualUsedDays = CalculateActualUsedDays(licenseStartDate, today);

                    // 🐛 修复：使用实际计算的天数和已记录天数的最大值，防止倒退
                    var newUsedDays = Math.Max(bestRecord.UsedDays, actualUsedDays);

                    Console.WriteLine($"[RobustUsageCounter] 新的使用日期 {today:yyyy-MM-dd}");
                    Console.WriteLine($"[RobustUsageCounter] 基于生效日期计算: {actualUsedDays} 天");
                    Console.WriteLine($"[RobustUsageCounter] 已记录使用天数: {bestRecord.UsedDays} 天");
                    Console.WriteLine($"[RobustUsageCounter] 最终使用天数: {newUsedDays} 天");

                    bestRecord.UsedDays = newUsedDays;
                    bestRecord.LastUsedDate = today;
                    bestRecord.UsageDates.Add(today);

                    // 保存到所有存储位置
                    SaveToAllStorages(bestRecord);
                }
                else if (today < bestRecord.LastUsedDate.Date)
                {
                    // 检测到时间倒退
                    return HandleTimeRewind(bestRecord, today, maxAllowedDays);
                }
                
                // 5. 验证使用天数
                return ValidateUsageDays(bestRecord, maxAllowedDays);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[RobustUsageCounter] 验证失败: {ex.Message}");
                return ValidationResult.Error($"验证使用天数时发生错误: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 从所有存储位置加载使用记录
        /// </summary>
        private List<UsageRecord> LoadAllUsageRecords()
        {
            var records = new List<UsageRecord>();
            
            // 1. 从文件存储加载
            foreach (var path in _storagePaths)
            {
                var record = LoadFromFile(path);
                if (record != null && ValidateRecord(record))
                {
                    records.Add(record);
                    Console.WriteLine($"[RobustUsageCounter] 从文件加载记录: {path} -> {record.UsedDays} 天");
                }
            }
            
            // 2. 从注册表加载
            var registryRecord = LoadFromRegistry();
            if (registryRecord != null && ValidateRecord(registryRecord))
            {
                records.Add(registryRecord);
                Console.WriteLine($"[RobustUsageCounter] 从注册表加载记录: {registryRecord.UsedDays} 天");
            }
            
            return records;
        }
        
        /// <summary>
        /// 从文件加载使用记录
        /// </summary>
        private UsageRecord? LoadFromFile(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    var encrypted = File.ReadAllText(filePath);
                    var json = DecryptData(encrypted);
                    return JsonSerializer.Deserialize<UsageRecord>(json);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[RobustUsageCounter] 从文件加载失败 {filePath}: {ex.Message}");
            }
            return null;
        }
        
        /// <summary>
        /// 从注册表加载使用记录
        /// </summary>
        private UsageRecord? LoadFromRegistry()
        {
            try
            {
                var value = Registry.GetValue(REGISTRY_KEY, REGISTRY_VALUE, null);
                if (value is int intValue && intValue != 0) // 0是系统默认值，忽略
                {
                    return DecodeUsageData(intValue);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[RobustUsageCounter] 从注册表加载失败: {ex.Message}");
            }
            return null;
        }
        
        /// <summary>
        /// 选择最可信的记录
        /// </summary>
        private UsageRecord? SelectBestRecord(List<UsageRecord> records)
        {
            if (!records.Any()) return null;

            // 选择使用天数最多的记录（防止用户通过删除部分文件来"回退"使用天数）
            return records.OrderByDescending(r => r.UsedDays).First();
        }

        /// <summary>
        /// 计算基于授权生效日期的实际使用天数
        /// </summary>
        private int CalculateActualUsedDays(DateTime licenseStartDate, DateTime currentDate)
        {
            var startDate = licenseStartDate.Date;
            var today = currentDate.Date;

            // 如果当前日期早于生效日期，使用天数为0
            if (today < startDate)
            {
                Console.WriteLine($"[RobustUsageCounter] 当前日期 {today:yyyy-MM-dd} 早于生效日期 {startDate:yyyy-MM-dd}，使用天数为0");
                return 0;
            }

            // 🐛 修复：正确计算从生效日期开始的使用天数
            // 使用生效日期作为第1天，计算到当前日期的天数
            var usedDays = (int)(today - startDate).TotalDays + 1;

            Console.WriteLine($"[RobustUsageCounter] 生效日期: {startDate:yyyy-MM-dd}, 当前日期: {today:yyyy-MM-dd}, 计算使用天数: {usedDays}");

            // 确保使用天数合理（至少1天，但不能超过合理范围）
            if (usedDays < 1)
            {
                Console.WriteLine($"[RobustUsageCounter] 警告：计算的使用天数小于1，调整为1");
                return 1;
            }

            if (usedDays > 3650) // 超过10年的异常情况
            {
                Console.WriteLine($"[RobustUsageCounter] 警告：计算的使用天数异常大({usedDays})，可能存在日期错误");
                return 1; // 重置为1天，避免异常
            }

            return usedDays;
        }
        
        /// <summary>
        /// 处理没有找到任何记录的情况
        /// </summary>
        private ValidationResult HandleNoRecord(int maxAllowedDays, DateTime licenseStartDate, DateTime today)
        {
            Console.WriteLine("[RobustUsageCounter] 未找到任何使用记录");
            
            // 检查是否可能是恶意删除
            if (IsLikelyMaliciousDeletion())
            {
                Console.WriteLine("[RobustUsageCounter] 检测到可能的恶意删除");
                return ValidationResult.Error(
                    "检测到可能的数据篡改。如果这是首次使用，请联系技术支持验证。"
                );
            }
            
            // 计算基于授权生效日期的实际使用天数
            var actualUsedDays = CalculateActualUsedDays(licenseStartDate, today);

            // 创建新记录
            var newRecord = new UsageRecord
            {
                UsedDays = actualUsedDays,
                LastUsedDate = today,
                FirstUsedDate = licenseStartDate.Date <= today ? licenseStartDate.Date : today,
                UsageDates = new List<DateTime> { today }
            };

            SaveToAllStorages(newRecord);

            Console.WriteLine($"[RobustUsageCounter] 创建新的使用记录，基于生效日期计算为第 {actualUsedDays} 天");
            return ValidationResult.Success(
                $"授权有效，已使用 {actualUsedDays} 天，剩余 {maxAllowedDays - actualUsedDays} 天",
                actualUsedDays,
                maxAllowedDays - actualUsedDays
            );
        }
        
        /// <summary>
        /// 检查是否可能是恶意删除
        /// </summary>
        private bool IsLikelyMaliciousDeletion()
        {
            try
            {
                // 检查程序安装时间
                var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
                var installTime = File.GetCreationTime(exePath);
                var daysSinceInstall = (DateTime.Now - installTime).Days;
                
                // 如果程序安装超过3天但没有使用记录，可能是被删除了
                if (daysSinceInstall > 3)
                {
                    Console.WriteLine($"[RobustUsageCounter] 程序安装已 {daysSinceInstall} 天，但无使用记录");
                    return true;
                }
                
                // 检查是否存在其他可疑迹象
                // 例如：临时文件夹中是否有残留的备份文件
                var tempBackups = Directory.GetFiles(Path.GetTempPath(), ".licenseapp_usage*");
                if (tempBackups.Length > 0)
                {
                    Console.WriteLine("[RobustUsageCounter] 发现临时备份文件残留");
                    return true;
                }
            }
            catch
            {
                // 检查失败时保守处理
            }
            
            return false;
        }
        
        /// <summary>
        /// 保存到所有存储位置
        /// </summary>
        private void SaveToAllStorages(UsageRecord record)
        {
            // 更新校验和
            record.CheckSum = CalculateCheckSum(record);
            
            // 保存到文件
            SaveToFiles(record);
            
            // 保存到注册表
            SaveToRegistry(record);
        }
        
        /// <summary>
        /// 保存到文件存储
        /// </summary>
        private void SaveToFiles(UsageRecord record)
        {
            var json = JsonSerializer.Serialize(record, new JsonSerializerOptions { WriteIndented = true });
            var encrypted = EncryptData(json);
            
            foreach (var path in _storagePaths)
            {
                try
                {
                    // 确保目录存在
                    var directory = Path.GetDirectoryName(path);
                    if (!string.IsNullOrEmpty(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }
                    
                    File.WriteAllText(path, encrypted);

                    // 设置隐藏属性
                    try
                    {
                        // 如果是用户主目录的隐藏文件夹，设置文件夹为隐藏
                        if (path.Contains(".CcdqLicenseApp"))
                        {
                            var hiddenDirectory = Path.GetDirectoryName(path);
                            if (!string.IsNullOrEmpty(hiddenDirectory) && Directory.Exists(hiddenDirectory))
                            {
                                var dirInfo = new DirectoryInfo(hiddenDirectory);
                                dirInfo.Attributes |= FileAttributes.Hidden;
                            }
                        }

                        // 设置文件为隐藏
                        File.SetAttributes(path, FileAttributes.Hidden);
                    }
                    catch
                    {
                        // 设置属性失败不影响功能
                    }
                    
                    Console.WriteLine($"[RobustUsageCounter] 保存到文件: {path}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[RobustUsageCounter] 保存到文件失败 {path}: {ex.Message}");
                }
            }
        }
        
        /// <summary>
        /// 保存到注册表
        /// </summary>
        private void SaveToRegistry(UsageRecord record)
        {
            try
            {
                var encodedValue = EncodeUsageData(record);
                Registry.SetValue(REGISTRY_KEY, REGISTRY_VALUE, encodedValue, RegistryValueKind.DWord);
                Console.WriteLine($"[RobustUsageCounter] 保存到注册表: {encodedValue}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[RobustUsageCounter] 保存到注册表失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 将使用数据编码为整数（用于注册表存储）
        /// </summary>
        private int EncodeUsageData(UsageRecord record)
        {
            // 编码格式：使用天数(8位) + 年份后两位(7位) + 月份(4位) + 日期(5位) + 校验位(8位)
            var year = record.LastUsedDate.Year % 100;
            var month = record.LastUsedDate.Month;
            var day = record.LastUsedDate.Day;
            var checksum = (record.UsedDays + year + month + day) % 256;
            
            return (record.UsedDays << 24) | (year << 17) | (month << 13) | (day << 8) | checksum;
        }
        
        /// <summary>
        /// 从整数解码使用数据
        /// </summary>
        private UsageRecord? DecodeUsageData(int encodedValue)
        {
            try
            {
                var usedDays = (encodedValue >> 24) & 0xFF;
                var year = ((encodedValue >> 17) & 0x7F) + 2000;
                var month = (encodedValue >> 13) & 0x0F;
                var day = (encodedValue >> 8) & 0x1F;
                var checksum = encodedValue & 0xFF;
                
                // 验证校验和
                if ((usedDays + (year % 100) + month + day) % 256 != checksum)
                {
                    Console.WriteLine("[RobustUsageCounter] 注册表数据校验和错误");
                    return null;
                }
                
                // 验证日期有效性
                if (month < 1 || month > 12 || day < 1 || day > 31)
                {
                    Console.WriteLine("[RobustUsageCounter] 注册表数据日期无效");
                    return null;
                }
                
                var lastUsedDate = new DateTime(year, month, day);
                return new UsageRecord
                {
                    UsedDays = usedDays,
                    LastUsedDate = lastUsedDate,
                    FirstUsedDate = lastUsedDate.AddDays(-(usedDays - 1)),
                    UsageDates = new List<DateTime>()
                };
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[RobustUsageCounter] 解码注册表数据失败: {ex.Message}");
                return null;
            }
        }
        
        /// <summary>
        /// 处理时间倒退
        /// </summary>
        private ValidationResult HandleTimeRewind(UsageRecord record, DateTime today, int maxAllowedDays)
        {
            var timeDifference = record.LastUsedDate.Date - today;
            Console.WriteLine($"[RobustUsageCounter] 检测到时间倒退: {timeDifference.TotalDays} 天");
            
            if (timeDifference.TotalDays <= 2)
            {
                // 小幅倒退，允许但警告
                var remainingDays = maxAllowedDays - record.UsedDays;
                return ValidationResult.Warning(
                    $"检测到时间调整，已使用 {record.UsedDays} 天，剩余 {remainingDays} 天",
                    record.UsedDays,
                    remainingDays
                );
            }
            
            // 大幅倒退，拒绝运行
            return ValidationResult.Error(
                $"检测到系统时间被大幅调整（{timeDifference.TotalDays:F0} 天），请确保系统时间正确"
            );
        }
        
        /// <summary>
        /// 验证使用天数
        /// </summary>
        private ValidationResult ValidateUsageDays(UsageRecord record, int maxAllowedDays)
        {
            if (record.UsedDays > maxAllowedDays)
            {
                return ValidationResult.Expired(
                    $"授权已过期！已使用 {record.UsedDays} 天，超过授权限制 {maxAllowedDays} 天",
                    record.UsedDays
                );
            }
            
            var remainingDays = maxAllowedDays - record.UsedDays;
            
            if (remainingDays <= 3)
            {
                return ValidationResult.Warning(
                    $"授权即将到期！已使用 {record.UsedDays} 天，仅剩 {remainingDays} 天",
                    record.UsedDays,
                    remainingDays
                );
            }
            
            return ValidationResult.Success(
                $"授权有效，已使用 {record.UsedDays} 天，剩余 {remainingDays} 天",
                record.UsedDays,
                remainingDays
            );
        }
        
        /// <summary>
        /// 验证记录完整性
        /// </summary>
        private bool ValidateRecord(UsageRecord record)
        {
            if (record == null) return false;
            if (record.UsedDays < 0) return false;
            if (record.FirstUsedDate > DateTime.Now.Date.AddDays(1)) return false;
            if (record.LastUsedDate > DateTime.Now.Date.AddDays(1)) return false;
            if (record.LastUsedDate < record.FirstUsedDate) return false;
            
            // 验证校验和（如果存在）
            if (!string.IsNullOrEmpty(record.CheckSum))
            {
                var expectedCheckSum = CalculateCheckSum(record);
                if (record.CheckSum != expectedCheckSum)
                {
                    Console.WriteLine("[RobustUsageCounter] 记录校验和不匹配");
                    return false;
                }
            }
            
            return true;
        }
        
        /// <summary>
        /// 计算校验和
        /// </summary>
        private string CalculateCheckSum(UsageRecord record)
        {
            var data = $"{record.UsedDays}|{record.FirstUsedDate:yyyyMMdd}|{record.LastUsedDate:yyyyMMdd}";
            using var sha256 = SHA256.Create();
            var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(data));
            return Convert.ToBase64String(hash);
        }
        
        /// <summary>
        /// 简单加密
        /// </summary>
        private string EncryptData(string data)
        {
            var bytes = Encoding.UTF8.GetBytes(data);
            var key = Encoding.UTF8.GetBytes("MySecretKey123");
            
            for (int i = 0; i < bytes.Length; i++)
            {
                bytes[i] ^= key[i % key.Length];
            }
            
            return Convert.ToBase64String(bytes);
        }
        
        /// <summary>
        /// 简单解密
        /// </summary>
        private string DecryptData(string encryptedData)
        {
            var bytes = Convert.FromBase64String(encryptedData);
            var key = Encoding.UTF8.GetBytes("MySecretKey123");
            
            for (int i = 0; i < bytes.Length; i++)
            {
                bytes[i] ^= key[i % key.Length];
            }
            
            return Encoding.UTF8.GetString(bytes);
        }
        
        /// <summary>
        /// 获取详细统计信息
        /// </summary>
        public string GetDetailedStatistics()
        {
            var sb = new StringBuilder();
            sb.AppendLine("=== 强化使用天数计数器统计 ===");

            var records = LoadAllUsageRecords();
            sb.AppendLine($"找到 {records.Count} 个有效记录:");

            foreach (var record in records.OrderByDescending(r => r.UsedDays))
            {
                sb.AppendLine($"- 使用天数: {record.UsedDays}, 最后使用: {record.LastUsedDate:yyyy-MM-dd}");
            }

            var bestRecord = SelectBestRecord(records);
            if (bestRecord != null)
            {
                sb.AppendLine($"\n最佳记录: {bestRecord.UsedDays} 天 (最后使用: {bestRecord.LastUsedDate:yyyy-MM-dd})");
            }

            return sb.ToString();
        }

        /// <summary>
        /// 重置使用记录（用于重新注册授权码）
        /// </summary>
        public bool ResetUsageRecords()
        {
            try
            {
                Console.WriteLine("[RobustUsageCounter] 开始重置使用记录...");

                int deletedCount = 0;

                // 删除所有文件存储的记录
                foreach (var path in _storagePaths)
                {
                    try
                    {
                        if (File.Exists(path))
                        {
                            File.Delete(path);
                            deletedCount++;
                            Console.WriteLine($"[RobustUsageCounter] 删除使用记录: {path}");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"[RobustUsageCounter] 删除文件失败 {path}: {ex.Message}");
                    }
                }

                // 清除注册表记录
                try
                {
                    Registry.SetValue(REGISTRY_KEY, REGISTRY_VALUE, 0, RegistryValueKind.DWord);
                    Console.WriteLine("[RobustUsageCounter] 清除注册表记录");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[RobustUsageCounter] 清除注册表失败: {ex.Message}");
                }

                Console.WriteLine($"[RobustUsageCounter] 重置完成，删除 {deletedCount} 个文件");
                return deletedCount > 0;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[RobustUsageCounter] 重置使用记录失败: {ex.Message}");
                return false;
            }
        }
    }
    
    /// <summary>
    /// 使用记录数据结构
    /// </summary>
    public class UsageRecord
    {
        public int UsedDays { get; set; }
        public DateTime LastUsedDate { get; set; }
        public DateTime FirstUsedDate { get; set; }
        public List<DateTime> UsageDates { get; set; } = new();
        public string CheckSum { get; set; } = "";
    }
    
    /// <summary>
    /// 验证结果
    /// </summary>
    public class ValidationResult
    {
        public bool IsValid { get; set; }
        public bool IsExpired { get; set; }
        public bool HasWarning { get; set; }
        public string Message { get; set; } = "";
        public int UsedDays { get; set; }
        public int RemainingDays { get; set; }
        
        public static ValidationResult Success(string message, int usedDays, int remainingDays)
        {
            return new ValidationResult 
            { 
                IsValid = true, 
                Message = message, 
                UsedDays = usedDays,
                RemainingDays = remainingDays
            };
        }
        
        public static ValidationResult Warning(string message, int usedDays, int remainingDays)
        {
            return new ValidationResult 
            { 
                IsValid = true, 
                HasWarning = true, 
                Message = message,
                UsedDays = usedDays,
                RemainingDays = remainingDays
            };
        }
        
        public static ValidationResult Expired(string message, int usedDays)
        {
            return new ValidationResult 
            { 
                IsValid = false, 
                IsExpired = true, 
                Message = message,
                UsedDays = usedDays,
                RemainingDays = 0
            };
        }
        
        public static ValidationResult Error(string message)
        {
            return new ValidationResult 
            { 
                IsValid = false, 
                Message = message 
            };
        }
    }
}
